package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuDetailService detailService;

    @Autowired
    private SkuService skuService;

    // 分页查询spu
    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
//        // 方法一
//        int current = Math.max(page, 1);
//        int size = Math.max(rows, 5);
//
//        Page<Spu> spuPage = query()
//                .eq(null != saleable, "saleable", saleable)
//                .eq(null != categoryId, " cid3", categoryId)
//                .eq(null != brandId, "brand_id", brandId)
//                .eq(null != id, "id", id)
//                .page(new Page<>(current, size));
//        long total = spuPage.getTotal();
//        long pages = spuPage.getPages();
//        List<Spu> list = spuPage.getRecords();
//
//        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(list);
//        for (SpuDTO spuDTO : spuDTOList) {
//            addSpuCategoryAndBrandName(spuDTO);
//        }
//
//        return new PageDTO<>(total, pages, spuDTOList);

        // 方法二
        Page<Spu> iPage = new Page<>(page, rows);

        page(iPage, new QueryWrapper<Spu>()
        .eq(id != null, "id", id)
        .eq(categoryId != null, "cid3", categoryId)
        .eq(brandId != null, "brand_id", brandId)
        .eq(saleable != null, "saleable", saleable));

        List<SpuDTO> spuDTOs = SpuDTO.convertEntityList(iPage.getRecords());
        spuDTOs.forEach(spuDTO -> {
            spuDTO.setBrandName(this.brandService.getById(spuDTO.getBrandId()).getName());
            String name = this.categoryService.listByIds(spuDTO.getCategoryIds())
                    .stream()
                    .map(Category::getName)
                    .collect(Collectors.joining("/"));

            spuDTO.setCategoryName(name);
        });

        return new PageDTO<>(iPage.getTotal(), iPage.getPages(), spuDTOs);
    }

    // 新增商品
    @Override
    @Transactional
    public void addGoods(SpuDTO spuDTO) {

        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(true);
        boolean flag = save(spu);
        if (!flag) {
            throw new LyException(500, "增加商品失败!");
        }

        // 新增商品详情
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        boolean success = detailService.save(spuDetail);
        if (!success) {
            throw new LyException(500, "新增商品详情失败!");
        }

        // 新增Sku
        List<Sku> skuList = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());

        // 批量新增
        skuService.saveBatch(skuList);
    }

    @Autowired
    private AmqpTemplate amqpTemplate;

    // 修改商品上下架(根据Id)
    @Override
    @Transactional
    public void setSpuSaleableState(Long id, Boolean saleable) {
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);

        boolean flag1 = updateById(spu);
        if (!flag1) {
            throw new LyException(500, "更新商品失败!");
        }

        // Sku sku = new Sku();
        // skuService.update(sku, new QueryWrapper<Sku>().eq("spu_id", id).eq("saleable", !saleable));
        boolean flag2 = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!flag2) {
            throw new LyException(500, "修改商品上架状态失败!");
        }

        String routingKey = saleable ? "up" : "down";

        this.amqpTemplate.convertAndSend("exchangeMQ", routingKey, spu.getId());
    }

    // 更新商品
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        Long spuId = spuDTO.getId();
        // 商品信息修改
        if (null != spuId) {
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean flag1 = updateById(spu);
            if (!flag1) {
                throw new LyException(500, "商品更新失败!");
            }
        }

        SpuDetailDTO spuDetailDto = spuDTO.getSpuDetail();
        if (spuDetailDto != null && spuDetailDto.getSpuId() != null) {
            SpuDetail spuDetail = spuDetailDto.toEntity(SpuDetail.class);
            boolean flag2 = detailService.updateById(spuDetail);
            if (!flag2) {
                throw new LyException(500, "商品更新失败!");
            }
        }

        List<SkuDTO> skus = spuDTO.getSkus();
        if (CollectionUtils.isEmpty(skus)) {
            return;
        }

        Map<Boolean, List<Sku>> map = skus
                .stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

        List<Sku> skuList = map.get(false);
        if (!CollectionUtils.isEmpty(skuList)) {
            List<Long> idList = skuList
                    .stream()
                    .map(Sku::getId)
                    .collect(Collectors.toList());
            skuService.removeByIds(idList);
        }

    }

    // 根据id查询spu及sku、spuDetail等
    @Override
    public SpuDTO querySkuAndSpuDetailById(Long id) {
        // 查询spuDetail
        Spu spu = getById(id);
        if (spu == null) {
            throw new LyException(400, "查不到指定Id的商品!");
        }

        SpuDTO spuDTO = new SpuDTO(spu);

        SpuDetail spuDetail = detailService.getById(id);
        if (spuDetail == null) {
            throw new LyException(400, "查不到指定Id的商品!");
        }

        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));

        // 查询sku
        List<Sku> skus = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(skus)) {
            throw new LyException(400, "查不到指定Id的商品!");
        }
        spuDTO.setSkus(SkuDTO.convertEntityList(skus));

        addSpuCategoryAndBrandName(spuDTO);

        return spuDTO;
    }


    // 给spu添加分类和品牌名称
    private void addSpuCategoryAndBrandName(SpuDTO spuDTO) {
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand != null) {
            spuDTO.setBrandName(brand.getName());
        }

        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if (!CollectionUtils.isEmpty(categories)) {
            String names = categories
                    .stream()
                    .map(Category::getName)
                    .collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }
}
